[Chapter 22] 22.4 SOCKS
Author: Simson Garfinkel & Gene Spafford
Date: 1999-02-04T00:17:13Z

#

| Chapter 22 Wrappers and Proxies |

## 22.4 SOCKS

SOCKS is a system that allows computers behind a firewall to access services on the Internet. The program allows you to centrally control how programs on your organization's network communicate with the Internet. With SOCKS, you can allow specific services to specific computers, disable access to individual hosts on the Internet, and log as much or as little as you want.

SOCKS was originally written by David Koblas and Michelle Koblas. It has since been extended by Ying-Da Lee at NEC's Systems Laboratory, and a commercially supported version is available from NEC. The name SOCKS stands for "SOCK-et-S." According to the SOCKS FAQ, "it was one of those `development names' that never left."

SOCKS consists of two parts:

SOCKS server

  A program that is run on a host that can communicate directly with both the Internet and the internal computers on your network (e.g., the firewall's gate).

SOCKS client programs

  Specially modified Internet client programs that know to contact the SOCKS server instead of sending requests directly to the Internet.

The standard SOCKS distribution comes with client programs for `finger`, `ftp`, `telnet`, and `whois`. SOCKS also includes a library you can use to create other SOCKS clients at will. Furthermore, many programs, such as NCSA Mosaic, include provisions for using SOCKS to negotiate firewalls.

SOCKS is available for most versions of UNIX, including SunOS, Sun Solaris, IRIX, Ultrix, HP-UX, AIX, Interactive Systems UNIX, OSF/1, NetBSD, UNIXWare, and Linux. A version called PC SOCKS, by Cornell Kinderknecht, is available for Microsoft Windows. A Macintosh version is under development.

### 22.4.1 What SOCKS Does

The SOCKS client software works by replacing calls to the UNIX socket functions - `connect`(), `getsocketname`(), `bind`(), `accept`(), `listen`() and `select`() - with its own versions of these functions. In practice, this replacement is done by adding a few macro definitions to the CFLAGS in the Makefile of the program that is used to compile the network client program, and then linking the resulting program with the SOCKS library.

When a SOCKS-modified client attempts to connect to a server on the Internet, the SOCKS library intercepts the connection attempt and instead opens up a connection to the SOCKS server. After the connection is established, the SOCKS client sends through the following information:

- Version number

- Connect request command

- Port number to which the client requested to connect

- IP address to which the client requested to connect

- Username of the person initiating the request

The SOCKS server then checks its access control list to see if the connection should be accepted or rejected. If the connection is accepted, the server opens up a connection to the remote machine and then relays all information back and forth. If the connection is rejected, the server disconnects from the client. This configuration is shown graphically in Figure 22.1.

#### Figure 22.1: : Using SOCKS for proxying

SOCKS can also be used to allow computers behind a firewall to receive connections. In this case, a connection is opened to the SOCKS server, which in turn gets ready to accept connections from the Internet.

SOCKS works only with TCP/IP; for UDP services (such as Archie), use UDP Relayer as described later in this chapter.

### 22.4.2 Getting SOCKS

Socks may be freely downloaded from the Internet. The address is:

> ftp://ftp.nec.com/pub/security/socks.cstc/
> http://www.socks.nec.com/

If you operate two nameservers to hide information from the Internet, you will also need to download the file Rgethostbyname.c. This file contains a function that can be used to query multiple nameservers to resolve a hostname.

There is a mailing list devoted to SOCKS and related issues. To join it, send the message "subscribe socks your-email-address" to majordomo@syl.dl.nec.com.

> NOTE: This section discusses SOCKS Version 4. At the time of this writing, SOCKS Version 5 was under development. New features in SOCKS 5 include strong authentication, authentication method negotiation, message integrity, message privacy, and support for UDP applications.

### 22.4.3 Getting SOCKS Running

After you have downloaded the system, you will need to follow these steps to get the system running:

1. Unpack the SOCKS distribution.

2. Decide whether you wish to have the SOCKS daemon started automatically when the system starts (boot time), or started by `inetd` when each SOCKS request is received.

   The advantage of having the daemon start automatically at system start-up is that the daemon will need to read its configuration file only once. Otherwise, the configuration file will have to be read each time a SOCKS connection is requested. We recommend that you have SOCKS started at boot time.

3. Edit the file Makefile in the main SOCKS directory and the file include/socks.h to reflect the policy of your site. Be sure to edit the variables found in Table 22.4.

   Table 22.4: Variables
   Variable | Location | Purpose/Setting
   --- | --- | ---
   SOCKS_DEFAULT_SERVER | include/socks.h | Set with the hostname of the computer that hosts the `sockd` daemon.
   SOCKS_DEFAULT_NS | include/socks.h | Set if the clients inside your firewall cannot look up the IP addresses of external hosts.
   NOT_THROUGH_INETD | include/socks.h | Set if `socksd` will be started automatically at system boot.
   SOCKS_CONF | include/socks.h | Location of the SOCKS configuration file for client machines.
   SOCKD_CONF | include/socks.h | Location of the SOCKS configuration file for the `sockd` daemon.
   MULTIHOMED_SERVER | include/socks.h | Set if `sockd` will be running on a multihomed server (a gate computer with two Ethernet ports).
   SOCKD_ROUTE_FILE | include/socks.h | Location of the SOCKS routing file, for use with multihomed servers.
   FACIST | Makefile | Causes SOCKS FTP client to log names of all files transferred.
   FOR_PS | Makefile | Causes `sockd` to display information about its current activity in the output from the ps command.
   SERVER_BIN_DIR | Makefile | Directory containing the `sockd` daemon.
   CLIENTS_BIN_DIR | Makefile | Directory containing the SOCKS client programs.

4. Compile SOCKS with a suitable C compiler.

5. Verify that `sockd` compiled properly and with the correct configuration by running `sockd` with the -ver option:

   >     % ./sockd -ver
   >      CSTC single-homed, stand-alone SOCKS proxy server version 4.2.
   >      Supports clients that use Rrcmd().
   >     %

6. Become superuser.

7. Install the SOCKS daemon in the location that you specified in the Makefile; you may be able to do this by typing "`make install.server`".

8. Add the SOCKS service to your /etc/services file. It should look like this:

   >     socks			1080/tcp

9. Now you need to set up the SOCKS configuration file. See the section called "The SOCKS Server Configuration File: /etc/sockd.conf below.

10. If you decided to have SOCKS start automatically at system boot time, modify your boot configuration files (either by adding a few lines to /etc/rc.local or by creating a new file in /etc/rc2.d/). You can set the start-up by adding a few lines that look like this:

    >     # Start SOCKS server
    >     if [ -f /usr/etc/sockd ]; then
    >           (echo -n "sockd... ")
    >                     >/dev/console
    >           /usr/etc/sockd >/dev/console 2>&1
    >     fi

11. If you decided to have SOCKS start from inetd (and you probably don't want to do this), add this line to the /etc/inetd.conf file:

    >     socks stream tcp nowait nobody /usr/etc/sockd

12. Start the sockd daemon manually, or reset inetd.

13. Test the system.

### 22.4.4 SOCKS and Usernames

SOCKS permits you to allow or deny access to Internet services based on both IP address and the username of the person on the local network making the request. There are two ways that SOCKS can determine the username of a person on the internal network:

1. Normally, a SOCKS client will send through the username of the person initiating the connection as part of the SOCKS protocol.

2. SOCKS can also use the `ident` protocol. For more information, see the section "Identification Protocol (auth) (TCP Port 113)" in Chapter 17.

### 22.4.5 SOCKS Identification Policy

The choice of identification policy is determined by the way in which the `sockd` program is invoked and by the /etc/sockd.conf configuration file.

Normally, `sockd` is invoked with one of three options:

>     sockd [-ver | -i | -I]

These options have the following meanings:

-ver

  Prints the `sockd` configuration information and exits.

-I

  Forces SOCKS to use the `ident` protocol. Denies access to any client that is not running the `ident` protocol. Also denies access to clients for which the username returned by the `ident` protocol does not match the username provided by the SOCKS protocol.

-i

  Less restrictive than -I. Denies access to clients when the username returned by the `ident` protocol is different from the username returned by the SOCKS protocol, but allows use of `sockd` by users who do not have `ident` running on their systems.

The identification options -i and -I can be overridden by a statement in the SOCKS configuration file, /etc/sockd.conf.

### 22.4.6 The SOCKS Server Configuration File: /etc/sockd.conf

The `sockd` configuration file, /etc/sockd.conf, allows you to control which TCP/IP connections are passed by the `sockd` daemon. As the daemon usually runs on a computer that has access to both your organization's internal network and the Internet, the sockd.conf file controls, in part, which services are passed between the two.

The `sockd` program doesn't know the difference between your internal and external networks. It simply receives connections, determines the parameters of the connections (username, source, requested destination, and TCP/IP service), then scans rules in the /etc/sockd.conf file to determine if the connections should be permitted or denied.

The /etc/sockd.conf file is an ASCII text file. Each line consists of a rule to either allow connections or reject (deny) them. The `sockd` program scans the file from the first line to the last line until a match is found. When a match is found, the action specified by the line is followed.

Lines in the /etc/sockd.conf file may be up to 1023 characters long. Each line has the following form:

>     [allow | deny] [?=auth] [*=username(s)|filename(s)]
>     source-address source-mask
>     [destination-address destination-mask]
>     [operator destination-port]
>     [: shell-command]

Fields are separated by spaces or tabs. If a number sign (#) is found on the line, everything after the number sign is assumed to be a comment, except as noted below.

If an incoming TCP/IP connection does not match any of the lines in the /etc/sockd.conf configuration file, it is rejected.

Here is an explanation of the fields:

allow | deny

  Specifies whether a connection matching the rule on this line should be allowed or denied.

?=auth

  If present, this field allows you to override the identification policy specified when the program was invoked. Specify "?=I" to cause `sockd` to reject the connection if the user on the client machine is not running `ident`, or if the name returned by `ident` is not the same as the username sent by the SOCKS client. Specify "?=i" to cause `sockd` to reject the connection if the name returned by `ident` is not the same as the name sent by the SOCKS client.

*=username(s)|filename(s)

  If present, causes the rule to match a particular username. You can also specify a filename, in which case the usernames are read out of the file (one username per line). Here are some examples:

Username | Result
*=simsong | Matches the user simsong.
*=fred,julie | Matches the users fred and julie.
*=/etc/goodusers | Matches anybody in the file /etc/goodusers.
*=fred,/etc/goodusers | Matches the user fred and all of the users in the file /etc/goodusers.

source-address source-mask

  The address and mask allow you to specify a match for a single IP address or a range of addresses. The source-address may be either an IP address in the form hhh.iii.jjj.kkk or an Internet hostname; the source-mask must be an IP address mask in the form hhh.iii.jjj.kkk.

  The source-mask specifies which bits of the source-address should be compared with the actual address of the incoming IP connection. Thus, a source-mask of 0.0.0.0 will cause the rule to match any IP address, while a source-mask of 255.255.255.255 will only allow for an exact match. These and other possibilities are explored in the table below:

source-address | source-mask | Result
--- | --- | ---
18.80.0.1 | 255.255.255.255 | Matches the host 18.80.0.1.
204.17.190.0 | 255.255.255.0 | Matches any host on the subnet 204.17.190.
10.80.0.1 | 255.0.0.0 | Matches any host on net 10.
0.0.0.0 | 0.0.0.0 | Matches every host on the Internet.

operator destination-port

  These optional arguments allow you to specify a particular TCP service or a range of TCP/IP ports. For example, you can specify "le 1023" to select all of the UNIX "privileged" ports, or you can specify "eq 25" to specify the SMTP port. The following table lists all of the operators:

operator | Meaning
--- | ---
eq | Equal to
neq | Not equal to
lt | Less than
le | Less than or equal to
gt | Greater than
ge | Greater than or equal to

: shell-command

  You can specify a command that will be executed when the line is matched. The command line is executed by the Bourne shell (/bin/sh). Before the line is executed, the following substitutions are made:

Token | Replaced With
--- | ---
%A | The fully qualified domain name (FQDN) of the client (the computer contacting `sockd`), if it can be determined; otherwise, the computer's IP address
%a | The IP address of the client
%c | The direction of the connection; replaced with connect if the client is attempting to make an outgoing connection, or `bind` if the client is waiting for an incoming connection
%p | The process ID of `sockd`
%S | The service name, if it can be determined from the /etc/services database; otherwise, the destination port number
%s | The destination port number
%U | The username reported by `identd`
%u | The username sent by the client program
%Z | The FQDN name of the destination host, if it can be determined; otherwise, the computer's IP address
%z | The IP address of the destination computer
%% | "%"

Obviously, token expansions that require that `sockd` look up a value in a database (such as %A, %S, and %Z) will take longer to execute than token expansions that merely report an IP or port number (such as %a, %s and %z).

This example command runs `finger` to determine the users on a particular computer, and then sends the results to the root account of the computer that is running sockd:

>     /usr/ucb/finger @%A | /bin/mailx -s 'SOCKS: rejected %u@%A' root

#### 22.4.6.1 #NO_IDENTD and #BAD_ID

In addition to the pattern matching described above, `sockd` allows you to specify rules that will match any computer contacting the `sockd` daemon which is not running the `ident` protocol, or for which the username returned by the ident protocol is different from the username provided in the initial `sockd` contact. These lines have the form:

>     #NO_IDENTD: command
>     #BAD_ID: command

#### 22.4.6.2 Example /etc/sockd.conf configuration files

Here are some example lines from an /etc/sockd.conf configuration file. The configuration file is designed to protect an organization that has placed a set of UNIX workstations on IP subnet 204.99.90.

deny

  204.99.90.0 255.255.255.0 204.99.90.0 255.255.255.0

  This initial rule disallows access to the internal network from internal computers using SOCKS. (Why tie up the SOCKS server if you don't need to?)

allow

  0.0.0.0 0.0.0.0 204.99.90.100 255.255.255.255 eq 25

  Allows connections to port 25 (SMTP) of the machine 204.99.90.100. This allows incoming electronic mail to that network.

allow

  204.99.90.100 255.255.255.255 0.0.0.0 0.0.0.0 eq 25

  Allows outgoing connections from the machine 204.99.90.100 to port 25 of any computer on the Internet. This rule allows the organization to send mail to outside computers.

allow

  204.99.90.0 255.255.255.0 0.0.0.0 0.0.0.0

  Allows outgoing connections from any host on subnet 204.99.90 to any computer on the Internet. If you have this rule, the previous rule is unnecessary.

deny

  0.0.0.0 0.0.0.0 204.99.90.255 255.255.255.000 eq 23 : \

  safe_finger @%A |/bin/mailx -s 'Telnet denied from %U/%A' root

This rather complex rule denies any attempted login to the organization's internal network. In addition to stopping the logins, it also does a `finger` of the computer from where the attempt is coming and sends email to the root account of the computer running `sockd`. If the remote machine is running the `ident` protocol, the username will be sent as well.

> NOTE: Do not use reverse `finger` for logging contacts on the `finger` port (port 79). Otherwise, a loop may result, with two `sockd` daemons continually attempting to `finger` each other until they are manually shut down or the disks fill up.

deny

  0.0.0.0 0.0.0.0 204.99.90.0 255.255.255.0

  Denies all other connections to the subnet 204.99.99. Strictly speaking, this rule is not necessary, as a connection that does not specifically match the "allow" rules above will be rejected.

### 22.4.7 SOCKS Client Configuration File: /etc/socks.conf

Each client that wishes to use the `sockd` server must also have its own configuration file. The configuration file has a syntax that is similar to, but slightly different from, the syntax of the /etc/sockd.conf file.

When a SOCKS client attempts to make an outgoing connection to another host on the Internet, or when it calls the Rbind() function to accept an incoming connection, the SOCKS library scans the /etc/socks.conf configuration file line by line, starting with the first line, until it finds a line that matches the requested connection. The library then performs the action that is specified in the file.

Each line in the file can have the following form:

>     deny [*=username(s)|filename(s)] destination-address destination-mask
>     	[operator destination-port]
>     	[: shell-command]

>     direct [*=username(s)|filename(s)] destination-address destination-mask
>     	[operator destination-port]
>     [: shell-command]

>     sockd [@=serverlist] [*=username(s)|filename(s)]
>     	destination-address destination-mask
>     	[operator destination-port]
>     	[: shell-command]

Most of these fields are similar to those in the /etc/sockd.conf file. The differences are described below:

deny

  The `deny` operator specifies that a TCP/IP connection that matches the line should be denied. (Remember, even though this connection will prevent the SOCKS package from making a connection to the site in question, the user may still have the option of connecting to the site using a client program that has not been linked with the SOCKS library. Thus, the `deny` operator running on the client computer is not a substitute for a suitable firewall choke. For more information on firewalls, see Chapter 21, Firewalls.)

direct

  The `direct` operator tells the SOCKS library that the TCP/IP connection should be sent directly through.

sockd [@=serverlist]

  The `sockd` operator tells the SOCKS library that the TCP/IP connection should be sent to the `sockd` daemon, which presumably will then pass it through to the outside network.

  The name of the host that is running the `sockd` server is compiled into the SOCKS library. It may also be specified on the command line, the SOCKS_SERVER environment variable, or it may be specified in the /etc/socks.conf configuration file using the @ argument. More than one server may be specified by separating the names with a comma, such as:

>     sockd @=socks1,socks2,sock3 0.0.0.0 0.0.0.0

In SOCKS version 4.2, the servers are tried in the order in which they appear in the configuration file. Thus, you can specify different servers in different orders on different clients to distribute the load. (A more intelligent approach, though, would be for the servers to be tried in random order.)

#### 22.4.7.1 Example /etc/socks.conf file

This simple configuration file, for an organization administrating the subnet 204.90.80, specifies that all connections to organization's internal subnet should go direct, while all connections to the outside network should go through the SOCKS server:

>     direct 204.90.80.0 255.255.255.0
>     sockd @=socks-server 0.0.0.0 0.0.0.0

22.3 tcpwrapper |  | 22.5 UDP Relayer